跳到主要内容

行和集合

行和集合是由一个或多个元素组成的复合值。

仅当您的数据库服务器是 GBase 8s 时才能应用这些主题的信息。

可以使用 SELECT 、UPDATE 、INSERT 和 DELETE 语句访问整个行或集合。但是,这些 SQL 语句不会让您访问集合或行中的任一元素。要访问元素,需要检索行或集合然后从行或集合的本地副本访问元素。

有关行和集合的更多信息,请参阅《GBase 8s SQL 指南:参考》和《GBase 8s 用户定义的例程和数据类型开发者指南》 。

分配和绑定行或集合缓冲区

当检索行或集合时,数据库服务器将行或集合放在 GBase 8s ODBC Driver应用程序本地的缓冲区中。

要调用和绑定集合或行缓冲区:

  1. 调用 ifx_rc_create() 分配缓冲区。
  2. 调用 SQLBindCol() 绑定缓冲区以绑定数据库列。
  3. 执行 SELECT 语句将行或集合传输到本地缓冲区。
  4. 使用行或集合缓冲区。
  5. 调用 ifx_rc_free() 释放缓冲区。

固定型缓冲区和不固定型缓冲区

固定型缓冲区和不固定型缓冲区之间存在一些差异。

下表描述了固定型缓冲区和不固定型缓冲区之间的差异。

缓冲区描述
固定型当调用 ifx_rc_create() 创建行或集合缓冲区时,为缓冲区指定下列数据类型:
● 缓冲区数据类型(行或一种集合类型)
● 行或集合中的元素的数据类型
当检索行或集合时,数据库服务器比较源和目标数据类型并将数据从GBase 8s SQL 数据类型转换为其它必需的数据类型。 在将数据检索到缓冲区中之前可以修改行或集合。
不固定型当调用 ifx_rc_create()创建行或集合缓冲区时,您只能指定缓冲区数据类型(行或集合),而不能指定元素类型。
当检索行或集合时,数据库服务器不会比较源和目标数据类型,因为未指定目标数据类型。相反,行或集合缓冲区采用源数据的数据类型。
在修改行或集合缓冲区后,您必须初始化它们。要初始化缓冲区,将行或集合检索到其中。
即使包含数据,缓冲区类型也不会保留。

缓冲区和内存分配

当将数据检索到包含行或集合的缓冲区时,GBase 8s ODBC Driver不会重复使用相同的缓冲区。

相反,GBase 8s ODBC Driver 执行以下操作:

  1. 创建行或集合缓冲区。
  2. 将缓冲区和给定的缓冲区句柄关联。
  3. 释放原来的缓冲区。

SQL 数据

数据库服务器调用转型函数将数据从源GBase 8s SQL 数据类型转换为目标 GBase 8s SQL 数据类型。

如果数据库服务器上的行或集合的数据类型与检索行或集合缓冲区的数据类型不同,则数据库服务器调用强制转型函数将数据从源 GBase 8s SQL 数据类型转换为目标GBase 8s SQL 数据类型。下表列出了源数据类型和目标数据类型每组组合的强制转型函数的提供者。数据类型提供的强制转型函数位于数据库服务器上。

源数据类型目标数据类型强制转型函数的提供者
内置内置数据库服务器
内置扩展数据类型
扩展内置数据类型
扩展扩展数据类型

执行本地访存

GBase 8s ODBC Driver从客户端计算机的一个位置检索行或集合到客户端计算机上的另一个位置时,执行本地访存。

本地访存在 SQL 数据转换上具有以下限制:

  • GBase 8s ODBC Driver无法转换在数据库服务器上强制转型函数的扩展数据类型。
  • GBase 8s ODBC Driver无法将一个命名行类型转换为另一种类型。只有数据库服务器可以执行此类型的转换。
  • 在检索整个行或集合时,GBase 8s ODBC Driver 无法转换 SQL 数据类型。因此,只有在源和目标的内部结构相同或者目标是不固定型缓冲区时,GBase 8s ODBC Driver可以执行整个行或集合的本地访存。

例如,如果您将本地集合定义为 list (char(1) not null),数据库服务器可以将 **list (int not null)**值从数据库服务器放到本地集合中。在此操作期间,数据库服务器将每个整数转换为字符串,并建立新的列表返回到客户端计算机。在将本地整数列表检索到字符列表时,不能在客户端计算机上执行此操作。

执行本地访存:

  1. 调用 ifx_rc_create() 分配一个行或集合缓冲区。
  2. 调用 SQLBindCol() 绑定缓冲区来处理本地行或集合。
  3. 执行 SELECT 语句将行或集合数据传输到本地缓冲区。
  4. 对于行或集合中的每一个元素,调用 ifx_rc_fetch() 将值复制到缓冲区。
  5. 使用行或集合缓冲区。
  6. 调用 ifx_rc_free() 释放缓冲区。

从数据库检索行和集合的示例

该样本程序 rcselect.c,从数据库检索并显示行和集合的数据。

该示例还说明了相同的客户端函数可以交替使用行和集合句柄。

可以在 UNIX™ 系统的 %GBS_HOME%/demo/clidemo 目录中找到 rcselect.c文件,在 Windows™ 系统的 %GBS_HOME%\demo\odbcdemo 目录中找到此文件。还可以找到有关如何在同一位置创建 odbc_demo 数据库的说明。

/*
** rcselect.c
**
** To access rows and collections
** OBDC Functions:
** SQLBindParameter
** SQLConnect
** SQLDisconnect
** SQLExecDirect
** SQLFetch
** SQLFreeStmt
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef NO_WIN32
#include <io.h>
#include <windows.h>
#include <conio.h>
#endif /*NO_WIN32*/

#include "infxcli.h"

#define BUFFER_LEN 25
#define ERRMSG_LEN 200

UCHAR defDsn[] = "odbc_demo";

int checkError (SQLRETURN rc,
SQLSMALLINT handleType,
SQLHANDLE handle,
char *errmsg)
{
SQLRETURN retcode = SQL_SUCCESS;

SQLSMALLINT errNum = 1;
SQLCHAR sqlState[6];
SQLINTEGER nativeError;
SQLCHAR errMsg[ERRMSG_LEN];
SQLSMALLINT textLengthPtr;

if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
while (retcode != SQL_NO_DATA)
{
retcode = SQLGetDiagRec (handleType, handle, errNum, sqlState,
&nativeError, errMsg, ERRMSG_LEN, &textLengthPtr);

if (retcode == SQL_INVALID_HANDLE)
{
fprintf (stderr, "checkError function was called with an
invalid handle!!\n");
return 1;
}

if ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
fprintf (stderr, "ERROR: %d: %s : %s \n", nativeError,
sqlState, errMsg);

errNum++;
}

fprintf (stderr, "%s\n", errmsg);
return 1; /* all errors on this handle have been reported */
}
else
return 0; /* no errors to report */
}

/*
** Executes the given select statement and assumes the results will be
** either rows or collections. The 'hrc' parameter may reference either
** a row or a collection. Rows and collection handles may often be used
** interchangeably.
**
** Each row of the select statement will be fetched into the given row or
** collection handle. Then each field of the row or collection will be
** individually converted into a character buffer and displayed.
**
** This function returns 0 if an error occurs, else returns 1
**
*/

int do_select (SQLHDBChdbc,
char* select_str,
HINFX_RChrc)
{
SQLHSTMT hRCStmt;
SQLHSTMT hSelectStmt;
SQLRETURN rc = 0;

short index, rownum;
short position = SQL_INFX_RC_ABSOLUTE;
short jump;

char fname[BUFFER_LEN];
char lname[BUFFER_LEN];
char rc_data[BUFFER_LEN];

SQLINTEGER cbFname = 0, cbLname = 0, cbHrc = 0;
SQLINTEGERcbPosition = 0, cbJump = 0, cbRCData = 0;

/* STEP A. Allocate the statement handles for the select statement and
** the statement used to retrieve the row/collection data.
*/

/* Allocate the statement handle */
rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hRCStmt);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step A -- Statement
Handle Allocation failed for row/collection
statement\nExiting!!"))
return 0;

/* Allocate the statement handle */
rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hSelectStmt);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step A -- Statement
Handle Allocation failed for select statement\nExiting!!"))
return 0;

fprintf (stdout, "STEP A done...statement handles allocated\n");


/* STEP B. Execute the select statement.
** Bind the result set columns -
** -- col1 = fname
** col2 = lname
** col3 = row/collection data
*/

/* Execute the select statement */
rc = SQLExecDirect (hSelectStmt, select_str, SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, "Error in Step B --
SQLExecDirect failed\n"))
return 0;

/* Bind the result set columns */
rc = SQLBindCol (hSelectStmt, 1, SQL_C_CHAR, (SQLPOINTER)fname,
BUFFER_LEN, &cbFname);
if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, "Error in Step B --
SQLBindCol failed for column 'fname'\n"))
return 0;

rc = SQLBindCol (hSelectStmt, 2, SQL_C_CHAR, (SQLPOINTER)lname,
BUFFER_LEN, &cbLname);
if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, "Error in Step B --
SQLBindCol failed for column 'lname'\n"))
return 0;

rc = SQLBindCol (hSelectStmt, 3, SQL_C_BINARY, (SQLPOINTER)hrc,
sizeof(HINFX_RC), &cbHrc);
if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, "Error in Step B --
SQLBindCol failed for row/collection column\n"))
return 0;

fprintf (stdout, "STEP B done...select statement executed and result set
columns bound\n");


/* STEP C. Retrieve the results.
*/

for (rownum = 1;; rownum++)
{
rc = SQLFetch (hSelectStmt);
if (rc == SQL_NO_DATA_FOUND)
{
fprintf (stdout, "No data found...\n");
break;
}
else if (checkError (rc, SQL_HANDLE_STMT, hSelectStmt, "Error in
Step C -- SQLFetch failed\n"))
return 0;


fprintf(stdout, "Retrieving row number %d:\n\tfname -- %s\n\tlname --
%s\n\tRow/Collection Data --\n", rownum, fname, lname);

/* For each row in the result set, display each field of the
retrieved row/collection */
for (index = 1;; index++)
{
strcpy(rc_data, "<null>");

/* Each value in the local row/collection will be fetched into a
* character buffer and displayed using fprintf().
*/

rc = SQLBindParameter (hRCStmt, 1, SQL_PARAM_OUTPUT, SQL_C_CHAR,
SQL_CHAR, 0, 0, rc_data, BUFFER_LEN, &cbRCData);
if (checkError (rc, SQL_HANDLE_STMT, hRCStmt, "Error in Step C --
SQLBindParameter failed (param 1)\n"))
return 0;

rc = SQLBindParameter (hRCStmt, 2, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_RC_COLLECTION, sizeof(HINFX_RC), 0, hrc,
sizeof(HINFX_RC), &cbHrc);
if (checkError (rc, SQL_HANDLE_STMT, hRCStmt, "Error in Step C --
SQLBindParameter failed (param 2)\n"))
return 0;

rc = SQLBindParameter (hRCStmt, 3, SQL_PARAM_INPUT, SQL_C_SHORT,
SQL_SMALLINT, 0, 0, &position, 0, &cbPosition);
if (checkError (rc, SQL_HANDLE_STMT, hRCStmt, "Error in Step C --
SQLBindParameter failed (param 3)\n"))
return 0;

jump = index;
rc = SQLBindParameter (hRCStmt, 4, SQL_PARAM_INPUT, SQL_C_SHORT,
SQL_SMALLINT, 0, 0, &jump, 0, &cbJump);
if (checkError (rc, SQL_HANDLE_STMT, hRCStmt, "Error in Step C --
SQLBindParameter failed (param 4)\n"))
return 0;

rc = SQLExecDirect(hRCStmt, "{ ? = call ifx_rc_fetch( ?, ?, ? ) }",
SQL_NTS);
if (rc == SQL_NO_DATA_FOUND)
{
break;
}
else if (checkError (rc, SQL_HANDLE_STMT, hRCStmt, "Error in
Step C -- SQLExecDirect failed\n"))
return 0;

/* Display retrieved row */
fprintf(stdout, "\t\t%d: %s\n", index, rc_data);
}
}

fprintf (stdout, "STEP C done...results retrieved\n");

/* Free the statement handles */
SQLFreeHandle (SQL_HANDLE_STMT, hSelectStmt);
SQLFreeHandle (SQL_HANDLE_STMT, hRCStmt);

return 1; /* no error */
}

/*
* This function allocates the row and collection buffers, passes
* them to the do_select() function, along with an appropriate select
* statement and then frees all allocated handles.
*/
int main (long argc,
char *argv[])
{
/* Declare variables
*/

/* Handles */
SQLHDBC hdbc;
SQLHENV henv;
SQLHSTMT hstmt;
HINFX_RC hrow, hlist;

/* Miscellaneous variables */

UCHAR dsn[20];/*name of the DSN used for connecting to the
database*/
SQLRETURN rc = 0;
int in;

int data_size = SQL_NTS;
char* listSelectStmt = "SELECT fname, lname, contact_dates FROM
customer";
char* rowSelectStmt = "SELECT fname, lname, address FROM
customer";

SQLINTEGER cbHlist = 0, cbHrow = 0;


/* STEP 1. Get data source name from command line (or use default).
** Allocate environment handle and set ODBC version.
** Allocate connection handle.
** Establish the database connection.
** Allocate the statement handle.
*/

/* If(dsn is not explicitly passed in as arg) */
if (argc != 2)
{
/* Use default dsn - odbc_demo */
fprintf (stdout, "\nUsing default DSN : %s\n", defDsn);
strcpy ((char *)dsn, (char *)defDsn);
}
else
{
/* Use specified dsn */
strcpy ((char *)dsn, (char *)argv[1]);
fprintf (stdout, "\nUsing specified DSN : %s\n", dsn);
}

/* Allocate the Environment handle */
rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (rc != SQL_SUCCESS)
{
fprintf (stdout, "Environment Handle Allocation failed\nExiting!!");
return (1);
}

/* Set the ODBC version to 3.5 */
rc = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3, 0);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 --
SQLSetEnvAttr failed\nExiting!!"))
return (1);

/* Allocate the connection handle */
rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 -- Connection
Handle Allocation failed\nExiting!!"))
return (1);

/* Establish the database connection */
rc = SQLConnect (hdbc, dsn, SQL_NTS, "", SQL_NTS, "", SQL_NTS);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- SQLConnect
failed\n"))
return (1);

/* Allocate the statement handle */
rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- Statement
Handle Allocation failed\nExiting!!"))
return (1);

fprintf (stdout, "STEP 1 done...connected to database\n");


/* STEP 2. Allocate an unfixed collection handle.
** Retrieve database rows containing a list.
** Reset the statement parameters.
*/

/* Allocate an unfixed list handle */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_BINARY,
SQL_INFX_RC_LIST, sizeof(HINFX_RC), 0, &hlist, sizeof(HINFX_RC),
&cbHlist);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLBindParameter (param 1) failed\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
0, 0, (UCHAR *) "list", 0, &data_size);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLBindParameter (param 2) failed\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{? = call ifx_rc_create(?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLExecDirect failed\n"))
goto Exit;

/* Retrieve databse rows containing a list */
if (!do_select (hdbc, listSelectStmt, hlist))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 2 done...list data retrieved\n");
fprintf (stdout,"\nHit <Enter> to continue...");
in = getchar ();

/* STEP 3. Allocate an unfixed row handle.
** Retrieve database rows containing a row.
** Reset the statement parameters.
*/

/* Allocate an unfixed row handle */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_BINARY,
SQL_INFX_RC_ROW, sizeof(HINFX_RC), 0, &hrow, sizeof(HINFX_RC),
&cbHrow);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 1) failed\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
0, 0, (UCHAR *) "row", 0, &data_size);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 2) failed\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{? = call ifx_rc_create(?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLExecDirect failed\n"))
goto Exit;

/* Retrieve databse rows containing a row */
if (!do_select (hdbc, rowSelectStmt, hrow))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 3 done...row data retrieved\n");


/* STEP 4. Free the row and list handles.
*/

/* Free the row handle */
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_RC_ROW, sizeof(HINFX_RC), 0, hrow, sizeof(HINFX_RC),
&cbHrow);

rc = SQLExecDirect(hstmt, (UCHAR *)"{call ifx_rc_free(?)}", SQL_NTS);

/* Free the list handle */
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_RC_LIST, sizeof(HINFX_RC), 0, hlist, sizeof(HINFX_RC),
&cbHlist);

rc = SQLExecDirect(hstmt, (UCHAR *)"{call ifx_rc_free(?)}", SQL_NTS);

fprintf (stdout, "STEP 4 done...row and list handles freed\n");

Exit:

/* CLEANUP: Close the statement handle.
** Free the statement handle.
** Disconnect from the datasource.
** Free the connection and environment handles.
** Exit.
*/

/* Close the statement handle */
SQLFreeStmt (hstmt, SQL_CLOSE);

/* Free the statement handle */
SQLFreeHandle (SQL_HANDLE_STMT, hstmt);

/* Disconnect from the data source */
SQLDisconnect (hdbc);

/* Free the environment handle and the database connection handle */
SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
SQLFreeHandle (SQL_HANDLE_ENV, henv);
fprintf (stdout,"\n\nHit <Enter> to terminate the program...\n\n");
in = getchar ();
return (rc);

在客户端创建行和列表的示例

此代码示例 rccreate.c,在客户端创建一个行和列表,添加项,并将它们插入到数据库。

可以在 UNIX™ 的 %GBS_HOME%/demo/clidemo 目录和 Windows™ 的%GBS_HOME%\demo\odbcdemo目录中找到 rccreate.c 文件。还可以找到有关如何在同一位置创建 odbc_demo 数据库的说明。

/*
** rccreate.c
**
** To create a collection & insert it into the database table
**
**
** OBDC Functions:
** SQLBindParameter
** SQLConnect
** SQLDisconnect
** SQLExecDirect
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef NO_WIN32
#include <io.h>
#include <windows.h>
#include <conio.h>
#endif /*NO_WIN32*/

#include "infxcli.h"

#define BUFFER_LEN 25
#define ERRMSG_LEN 200

UCHAR defDsn[] = "odbc_demo";

int checkError (SQLRETURNrc,
SQLSMALLINT handleType,
SQLHANDLE handle,
char *errmsg)
{
SQLRETURN retcode = SQL_SUCCESS;

SQLSMALLINT errNum = 1;
SQLCHAR sqlState[6];
SQLINTEGER nativeError;
SQLCHAR errMsg[ERRMSG_LEN];
SQLSMALLINT textLengthPtr;
if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
while (retcode != SQL_NO_DATA)
{
retcode = SQLGetDiagRec (handleType, handle, errNum, sqlState,
&nativeError, errMsg, ERRMSG_LEN, &textLengthPtr);

if (retcode == SQL_INVALID_HANDLE)
{
fprintf (stderr, "checkError function was called with an
invalid handle!!\n");
return 1;
}

if ((retcode == SQL_SUCCESS) || (retcode ==
SQL_SUCCESS_WITH_INFO)) fprintf (stderr, "ERROR: %d: %s
: %s \n", nativeError, sqlState, errMsg);

errNum++;
}

fprintf (stderr, "%s\n", errmsg);
return 1; /* all errors on this handle have been reported */
}
else
return 0; /* no errors to report */
}

int main (long argc,
char *argv[])
{
/* Declare variables
*/

/* Handles */
SQLHDB hdbc;
SQLHENV henv;
SQLHSTMT hstmt;

HINFX_RC hrow;
HINFX_RC hlist;

/* Miscellaneous variables */
UCHAR dsn[20];/*name of the DSN used for connecting to the
database*/
SQLRETURN rc = 0;
int i, in;
int data_size = SQL_NTS;
short position = SQL_INFX_RC_ABSOLUTE;
short jump;

UCHAR row_data[4][BUFFER_LEN] = {"520 Topaz Way", "Redwood City",
"CA", "94062"};
int row_data_size = SQL_NTS;

UCHAR list_data[2][BUFFER_LEN] = {"1991-06-20", "1993-07-17"};
int list_data_size = SQL_NTS;

char* insertStmt = "INSERT INTO customer VALUES (110, 'Roy',
'Jaeger', ?, ?)";
SQLINTEGER cbHrow = 0, cbHlist = 0, cbPosition = 0, cbJump = 0;
/* STEP 1. Get data source name from command line (or use default).
** Allocate environment handle and set ODBC version.
** Allocate connection handle.
** Establish the database connection.
** Allocate the statement handle.
*/

/* If(dsn is not explicitly passed in as arg) */
if (argc != 2)
{
/* Use default dsn - odbc_demo */
fprintf (stdout, "\nUsing default DSN : %s\n", defDsn);
strcpy ((char *)dsn, (char *)defDsn);
}
else
{
/* Use specified dsn */
strcpy ((char *)dsn, (char *)argv[1]);
fprintf (stdout, "\nUsing specified DSN : %s\n", dsn);
}
/* Allocate the Environment handle */
rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (rc != SQL_SUCCESS)
{
fprintf (stdout, "Environment Handle Allocation failed\nExiting!!");
return (1);
}

/* Set the ODBC version to 3.5 */
rc = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3, 0);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 --
SQLSetEnvAttr failed\nExiting!!"))
return (1);

/* Allocate the connection handle */
rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 -- Connection
Handle Allocation failed\nExiting!!"))
return (1);

/* Establish the database connection */
rc = SQLConnect (hdbc, dsn, SQL_NTS, "", SQL_NTS, "", SQL_NTS);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- SQLConnect
failed\n"))
return (1);

/* Allocate the statement handle */
rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt );
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- Statement
Handle Allocation failed\nExiting!!"))
return (1);

fprintf (stdout, "STEP 1 done...connected to database\n");


/* STEP 2. Allocate fixed-type row handle -- this creates a non-null row
** buffer, each of whose values is null, and can be updated.
** Allocate a fixed-type list handle -- this creates a non-null
** but empty list buffer into which values can be inserted.
** Reset the statement parameters.
*/

/* Allocate a fixed-type row handle -- this creates a row with each
value empty */

rc = SQLBindParameter (hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_BINARY,
SQL_INFX_RC_ROW, sizeof(HINFX_RC), 0, &hrow, sizeof(HINFX_RC),
&cbHrow);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLBindParameter (param 1) failed for row handle\n")) goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
0, 0, (UCHAR *) "ROW(address1 VARCHAR(25), city VARCHAR(15), state
VARCHAR(15), zip VARCHAR(5))", 0, &data_size);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLBindParameter (param 2) failed for row handle\n"))
goto Exit;

rc = SQLExecDirect (hstmt, (UCHAR *) "{? = call ifx_rc_create(?)}",
SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLExecDirect failed for row handle\n"))
goto Exit;

/* Allocate a fixed-type list handle */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_BINARY,
SQL_INFX_RC_LIST, sizeof(HINFX_RC), 0, &hlist, sizeof(HINFX_RC),
&cbHlist);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLBindParameter (param 1) failed for list handle\n"))
goto Exit;

data_size = SQL_NTS;
rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
0, 0, (UCHAR *) "LIST (DATETIME YEAR TO DAY NOT NULL)",0,
&data_size);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLBindParameter (param 2) failed for list handle\n"))
goto Exit;

rc = SQLExecDirect (hstmt, (UCHAR *) "{? = call ifx_rc_create(?)}",
SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLExecDirect failed for list handle\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 2 done...fixed-type row and collection handles
allocated\n");

/* STEP 3. Update the elements of the fixed-type row buffer allocated.
** Insert elements into the fixed-type list buffer allocated.
** Reset the statement parameters.
*/

/* Update elements of the row buffer */
for (i=0; i<4; i++)
{
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_RC_ROW, sizeof(HINFX_RC), 0, hrow, sizeof(HINFX_RC),
&cbHrow);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 1) failed for row handle\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR,
SQL_CHAR, BUFFER_LEN, 0, row_data[i], 0, &row_data_size);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 2) failed for row handle\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 3, SQL_PARAM_INPUT, SQL_C_SHORT,
SQL_SMALLINT, 0, 0, &position, 0, &cbPosition);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 3) failed for row handle\n"))
goto Exit; jump = i + 1;
rc = SQLBindParameter (hstmt, 4, SQL_PARAM_INPUT, SQL_C_SHORT,
SQL_SMALLINT, 0, 0, &jump, 0, &cbJump);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 4) failed for row handle\n"))
goto Exit;

rc = SQLExecDirect (hstmt,
(UCHAR *)"{call ifx_rc_update(?, ?, ?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLExecDirect failed for row handle\n"))
goto Exit;
}

/* Insert elements into the list buffer */
for (i=0; i<2; i++)
{
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_RC_LIST, sizeof(HINFX_RC), 0, hlist, sizeof(HINFX_RC),
&cbHlist);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 1) failed for list handle\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR,
SQL_DATE, 25, 0, list_data[i], 0, &list_data_size);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 2) failed for list handle\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 3, SQL_PARAM_INPUT, SQL_C_SHORT,
SQL_SMALLINT, 0, 0, &position, 0, &cbPosition);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 3) failed for list handle\n"))
goto Exit;

jump = i + 1;
rc = SQLBindParameter (hstmt, 4, SQL_PARAM_INPUT, SQL_C_SHORT,
SQL_SMALLINT, 0, 0, &jump, 0, &cbJump);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter (param 4) failed for list handle\n"))
goto Exit;

rc = SQLExecDirect (hstmt,
(UCHAR *)"{call ifx_rc_insert( ?, ?, ?, ? )}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLExecDirect failed for list handle\n"))
goto Exit;
}

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 3 done...row and list buffers populated\n");


/* STEP 4. Bind parameters for the row and list handles.
** Execute the insert statement to insert the new row into table
** 'customer'.
*/

rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_RC_COLLECTION, sizeof(HINFX_RC), 0, hrow,
sizeof(HINFX_RC), &cbHrow);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_RC_COLLECTION, sizeof(HINFX_RC), 0, hlist,
sizeof(HINFX_RC), &cbHlist);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, (UCHAR *)insertStmt, SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLExecDirect failed\n"))
goto Exit;

fprintf (stdout, "STEP 4 done...new row inserted into table
'customer'\n");


/* STEP 5. Free the row and list handles.
*/

/* Free the row handle */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_RC_ROW, sizeof(HINFX_RC), 0, hrow, sizeof(HINFX_RC),
&cbHrow);

rc = SQLExecDirect(hstmt, (UCHAR *)"{call ifx_rc_free(?)}", SQL_NTS);

/* Free the list handle */
rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_RC_LIST, sizeof(HINFX_RC), 0, hlist, sizeof(HINFX_RC),
&cbHlist);

rc = SQLExecDirect(hstmt, (UCHAR *)"{call ifx_rc_free(?)}", SQL_NTS);

fprintf (stdout, "STEP 5 done...row and list handles freed\n");

Exit:

/* CLEANUP: Close the statement handle.
** Free the statement handle.
** Disconnect from the datasource.
** Free the connection and environment handles.
** Exit.
*/

/* Close the statement handle */
SQLFreeStmt (hstmt, SQL_CLOSE);

/* Free the statement handle */
SQLFreeHandle (SQL_HANDLE_STMT, hstmt);

/* Disconnect from the data source */
SQLDisconnect (hdbc);

/* Free the environment handle and the database connection handle */
SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
SQLFreeHandle (SQL_HANDLE_ENV, henv);

fprintf (stdout,"\n\nHit <Enter> to terminate the program...\n\n");
in = getchar ();
return (rc);

修改行或集合

GBase 8s ODBC Driver 提供可用于修改行和集合的函数。

下表提供了 GBase 8s ODBC Driver提供的用于修改行和集合的函数的概述。

函数修改集合
ifx_rc_delete()删除元素
ifx_rc_insert()插入元素是(参阅下表。)
ifx_rc_setnull()将行或集合设置为空
ifx_rc_update()更改元素的值

下表描述了您可以插入元素的集合的位置。只能在 SET 或 MULTISET 集合的末尾插入元素,因为这些类型的集合中的元素的位置没有顺序。

开始中间末尾
List
Multiset
Set

提示: 如果您只需要插入或更新具有文字值的的行或集合,则不需要使用行或集合缓冲区。相反,您可以在 INSERT 语句的 INTO 子句或 UPDATE 语句的 SET 子句中显式列出文字值。

每一行和集合都维护一个指向行或集合中的当前元素的查找位置。创建行或集合时,该查找位置指向行或集合中的第一个元素。所有对客户端函数的调用都共享同一个行或集合缓冲区的查找位置。因此,一个客户端函数会影响另一个使用相同缓冲区句柄的客户端函数。下表描述了客户端函数如何更改查找位置。

客户端函数作用于变更
ifx_rc_delete()指定的位置。将查找位置设置为删除后的位置。
ifx_rc_fetch()指定的位置。将查找位置设置到指定的位置。
ifx_rc_insert()指定位置之前。将查找位置设置到指定的位置。
ifx_rc_update()指定的位置。将查找位置设置到指定的位置。

检索行或集合的信息

GBase 8s ODBC Driver提供可用于检索有关行和集合的函数。

下表提供了 GBase 8s ODBC Driver用于检索行和集合信息的函数概述。ifx_rc_describe() 函数返回行或集合中元素的数据类型。

函数信息参考
ifx_rc_count()列数ifx_rc_count() 函数
ifx_rc_describe()数据类型信息ifx_rc_describe() 函数
ifx_rc_isnull()指示是否为空的值ifx_rc_isnull() 函数
ifx_rc_typespec()类型描述ifx_rc_typespec() 函数